package tools

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

// FileWriter 实现了写入文件内容的工具
// 该工具允许ReAct智能体创建或修改文本文件
type FileWriter struct{}

// Name 返回工具的唯一标识名称
func (fw *FileWriter) Name() string {
	return "write_file"
}

// Description 返回工具的功能描述
func (fw *FileWriter) Description() string {
	return `将内容写入文本文件。如果文件不存在则创建，如果存在则覆盖原有内容，提供安全的文件写入能力。

**参数说明：**
- file_path (string, 必需): 要写入的文件路径
  - 支持相对路径和绝对路径
  - 只支持写入文本文件
  - 禁止写入系统目录和可执行文件
  - 禁止覆盖重要系统文件
- content (string, 必需): 要写入的内容
  - 支持任意文本内容
  - 自动处理特殊字符和编码
  - 内容长度无严格限制
- create_dirs (boolean, 可选): 是否自动创建不存在的目录，默认为false
  - true: 自动创建缺失的目录结构
  - false: 只在现有目录中创建文件

**使用示例：**
` + "```json" + `
{
  "type": "action",
  "action": "write_file",
  "parameters": {
    "file_path": "output.txt",
    "content": "Hello, World!"
  }
}
` + "```" + `

` + "```json" + `
{
  "type": "action",
  "action": "write_file",
  "parameters": {
    "file_path": "data/info.json",
    "content": "{\"name\": \"test\", \"value\": 123}",
    "create_dirs": true
  }
}
` + "```" + `

**返回结果：**
- 成功: 文件路径、大小、写入字节数和内容预览
- 失败: 错误信息（安全检查失败、权限不足等）
- 取消: "文件写入已取消"`
}

// confirmWrite 请求用户确认是否写入文件
func (fw *FileWriter) confirmWrite(filePath string, overwrite bool) bool {
	// 为了测试目的，可以设置环境变量跳过确认
	if os.Getenv("AISH_SKIP_CONFIRM") == "true" {
		return true
	}

	reader := bufio.NewReader(os.Stdin)

	if overwrite {
		fmt.Printf("\n[WARNING] 确认覆盖文件: %s\n", filePath)
	} else {
		fmt.Printf("\n[FILE] 确认创建文件: %s\n", filePath)
	}
	fmt.Print("请确认是否写入？(y/N): ")

	input, err := reader.ReadString('\n')
	if err != nil {
		return false
	}

	input = strings.TrimSpace(strings.ToLower(input))
	return input == "y" || input == "yes"
}

// createDirectories 创建目录（如果需要）
func (fw *FileWriter) createDirectories(filePath string) error {
	dir := filepath.Dir(filePath)
	if dir == "." || dir == "/" {
		return nil // 当前目录或根目录不需要创建
	}

	// 检查目录是否存在
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		// 创建目录
		if err := os.MkdirAll(dir, 0755); err != nil {
			return fmt.Errorf("创建目录失败: %v", err)
		}
		fmt.Printf("创建目录: %s\n", dir)
	}

	return nil
}

// Execute 执行文件写入操作
func (fw *FileWriter) Execute(args map[string]interface{}) (string, error) {
	// 提取必需参数
	filePath, ok := args["file_path"].(string)
	if !ok {
		return "", fmt.Errorf("file_path 参数是必需的，必须是字符串类型")
	}

	content, ok := args["content"].(string)
	if !ok {
		return "", fmt.Errorf("content 参数是必需的，必须是字符串类型")
	}

	filePath = strings.TrimSpace(filePath)
	if filePath == "" {
		return "", fmt.Errorf("file_path 不能为空")
	}

	// 检查是否需要创建目录
	createDirs := false
	if createDirsParam, exists := args["create_dirs"]; exists {
		createDirs, ok = createDirsParam.(bool)
		if !ok {
			// 尝试转换字符串类型的布尔值
			if createDirsStr, ok := createDirsParam.(string); ok {
				createDirs = strings.ToLower(createDirsStr) == "true"
			}
		}
	}

	// 检查文件是否存在
	fileExists := false
	if _, err := os.Stat(filePath); err == nil {
		fileExists = true
	}

	// 如果需要创建目录，先创建目录
	if createDirs {
		if err := fw.createDirectories(filePath); err != nil {
			return "", err
		}
	}

	// 用户确认
	if !fw.confirmWrite(filePath, fileExists) {
		return "文件写入已取消", nil
	}

	// 写入文件
	file, err := os.Create(filePath)
	if err != nil {
		return "", fmt.Errorf("无法创建文件: %v", err)
	}
	defer file.Close()

	// 写入内容
	bytesWritten, err := file.WriteString(content)
	if err != nil {
		return "", fmt.Errorf("写入文件时出错: %v", err)
	}

	// 确保内容写入磁盘
	if err := file.Sync(); err != nil {
		return "", fmt.Errorf("同步文件时出错: %v", err)
	}

	// 获取文件信息
	fileInfo, err := os.Stat(filePath)
	if err != nil {
		return "", fmt.Errorf("获取文件信息时出错: %v", err)
	}

	operation := "创建"
	if fileExists {
		operation = "覆盖"
	}

	result := fmt.Sprintf("文件%s成功！\n文件路径: %s\n文件大小: %d bytes\n写入字节数: %d",
		operation, filePath, fileInfo.Size(), bytesWritten)

	// 如果内容较长，显示部分内容
	if len(content) > 100 {
		result += fmt.Sprintf("\n内容预览:\n%s... (共 %d 字符)", content[:100], len(content))
	} else {
		result += fmt.Sprintf("\n文件内容:\n%s", content)
	}

	return result, nil
}

// NewFileWriter 创建并返回一个新的FileWriter实例
func NewFileWriter() *FileWriter {
	return &FileWriter{}
}
